// @coding utf8


#include <iostream>
extern "C" {
#include <lualib.h>
#include <lauxlib.h>
}
#include <sol/sol.hpp>
#include <inttypes.h>
#include <limits>

// void test_lua_api()
// {
//     lua_State* lstate = luaL_newstate();

//     luaL_openlibs(lstate);
//     luaL_dostring(lstate, "print(666)");

//     lua_close(lstate);
// }

// int add(int a, int b)
// {
//     return a + b;
// }

// int my_exception_handler(lua_State* L, sol::optional<const std::exception&> maybe_exception, sol::string_view description) {
// 	// L is the lua state, which you can wrap in a state_view if necessary
// 	// maybe_exception will contain exception, if it exists
// 	// description will either be the what() of the exception or a description saying that we hit the general-case catch(...)
// 	std::cout << "An exception occurred in a function, here's what it says ";
// 	if (maybe_exception) {
// 		std::cout << "(straight from the exception): ";
// 		const std::exception& ex = *maybe_exception;
// 		std::cout << ex.what() << std::endl;
// 	}
// 	else {
// 		std::cout << "(from the description parameter): ";
// 		std::cout.write(description.data(), static_cast<std::streamsize>(description.size()));
// 		std::cout << std::endl;
// 	}

// 	// you must push 1 element onto the stack to be
// 	// transported through as the error object in Lua
// 	// note that Lua -- and 99.5% of all Lua users and libraries -- expects a string
// 	// so we push a single string (in our case, the description of the error)
// 	return sol::stack::push(L, description);
// }

// inline sol::protected_function_result my_script_pass_on_error(lua_State*, sol::protected_function_result result) {
//         sol::error err = result;
// 	    std::cout << err.what() << std::endl;
// 		return result;
// 	}

// // 模拟插件
// extern "C"
// {
//     int luaopen_myplugin(lua_State* l)
//     {
//         sol::state_view lua(l);
//         auto named_table = lua.create_named_table("myplugin");
//         named_table["add1"] = &add;
//         return 0;
//     }
// }


// void test_sol2()
// {
//     sol::state lua;
//     lua.set_exception_handler(my_exception_handler);
//     lua.open_libraries();
//     // 加载并执行 Lua 代码
//     lua.script("print('Hello from sol2 in C++!')");
//     lua["add"] = &add;
//     lua.script("print(add(111, 555))");

//     lua.script("print(add(111, 555, 111))");
//     //lua.script("print(add(111))");
//     lua.safe_script("print(add(111))", my_script_pass_on_error);
//     lua.script("print('xxx')");

//     //auto myplugin = lua.require("myplugin", luaopen_myplugin);
//     //std::function<int(int,int)> add1 = myplugin["add1"];
//     //lua.script("print(myplugin)");
//     //lua.safe_script("print(myplugin.add1(1,2))", my_script_pass_on_error);
//     //lua.script("print(add1)");
//     //lua.script("require('myplugin')");

//     lua.script("function lua_hell(n) print('lua hello=%s', n) end ");
//     sol::function func = lua["lua_hell"];
//     func(1);
//     std::function<void(int)> func1 = func;
//     func1(2);
// }

#define XLOG_DEBUG()
#define XLOG_INFO()
#define XLOG_WARN()
#define XLOG_ERROR()

#define XLOG_DEBUG_FMT(fmt, ...)
#define XLOG_INFO_FMT(fmt, ...)
#define XLOG_WARN_FMT(fmt)
#define XLOG_ERROR_FMT(fmt, ...)

#define XLOG_DEBUG_INTERNAL(name)
#define XLOG_DEBUG_INTERNAL(name)
#define XLOG_WARN_INTERNAL(name)
#define XLOG_ERR_INTERNAL(name)

const int MAX_int8_to_string_buf_len = 1 + 3 + 1;  // int8字符串最大长度：(符号+数字+\0)  [-128，127] \0
const int MAX_int16_to_string_buf_len = 7;  // int16字符串最大长度：
const int MAX_int32_to_string_buf_len = 12;
const int MAX_int64_to_string_buf_len = 21;


const int DEFAULT_LogMessageDataSize = 255;

class LogEvent
{
public:
    LogEvent() :
        msg(default_data),
        msg_end(msg),
        msg_cap(DEFAULT_LogMessageDataSize)
    {
        *msg_end = 0;
    }

public:

    /// @brief 获取消息字符串地址
    /// @return 原始字符串地址
    const char* get_msg()
    {
        return msg;
    }

    /// @brief 获取消息长度(含\0)
    /// @return
    size_t get_msg_len()
    {
        return msg_end - msg;
    }

    void write_string(const char* str)
    {
        size_t inc_len = strlen(str);
        size_t msg_len = get_msg_len();
        size_t new_msg_len = get_msg_len() + inc_len;
        if (new_msg_len > msg_cap)
            recapacity(new_msg_len);
        memcpy(msg_end, str, inc_len);
        msg_end = msg_end + inc_len;
        *msg_end = 0;
    }

    void write_char(char ch)
    {
        size_t new_msg_len = get_msg_len();
        if (new_msg_len > msg_cap)
            recapacity(new_msg_len);
        *msg_end = ch;
        msg_end += 1;
        *msg_end = 0;
    }

    void write_int8(int8_t n)
    {
        size_t msg_len = get_msg_len();
        size_t new_msg_len = msg_len + MAX_int8_to_string_buf_len;
        if (new_msg_len > msg_cap)
            recapacity(new_msg_len);
        size_t inc_len = snprintf(msg_end, MAX_int8_to_string_buf_len, "%" PRId8, n);
        msg_end += inc_len;
    }

    void write_int16(int16_t n);
    void write_int32(int32_t n);
    void write_int64(int32_t n);
    void write_float(float f);
    void write_double(double d);

protected:



    ///@brief 重设容量
    ///@param cap 需要的容量
    size_t recapacity(size_t cap)
    {
        if (msg_cap >= cap)
            return msg_cap;
        char* old_msg = msg;
        size_t old_len = msg_end - msg;
        ///@todo cap增长需要有策略，暂定64/128/255/512/1024的整数倍，给出两种策略，一种指定n的整数倍，一种手工指定增长序列
        msg = new char[cap];
        memcpy(msg, old_msg, old_len);
        msg_end = msg + old_len;
        if (old_msg != default_data)
        {
            delete[] old_msg;
        }
        return cap;
    }

public:
    char* func = nullptr;
    char* file = nullptr;
    int32_t line = 0;
    char* msg = nullptr;      // 永远指向一个\0结尾的字符串
    char* msg_end = nullptr;  // 消息结束位置(\0的地址)
    size_t msg_cap = DEFAULT_LogMessageDataSize;  // 包含了 \0
    char default_data[DEFAULT_LogMessageDataSize];
};

class Logger
{
public:
    void append();
};

class XLua
{
public:
    XLua();
    ~XLua();

    int run(int argc, const char* argv[])
    {
        if (argc < 1)
            return 0;
        _entry = argv[1];
        //_lua_state.do_file()
    }

protected:
    sol::state _lua_state;
    //std::vector<std::string> _argv;
    std::string _entry;
};

void test_logevent()
{
    LogEvent event;
    std::cout << event.get_msg() << std::endl;
    event.write_char('a');
    std::cout << event.get_msg() << std::endl;
    event.write_char('b');
    std::cout << event.get_msg() << std::endl;
    event.write_char('c');
    std::cout << event.get_msg() << std::endl;


    event.write_int8(1);
    std::cout << event.get_msg() << std::endl;
    event.write_int8(2);
    std::cout << event.get_msg() << std::endl;
    event.write_int8(3);
    std::cout << event.get_msg() << std::endl;


    event.write_int8(-1);
    std::cout << event.get_msg() << std::endl;
    event.write_int8(-2);
    std::cout << event.get_msg() << std::endl;
    event.write_int8(-3);
    std::cout << event.get_msg() << std::endl;

    event.write_int8(std::numeric_limits<int8_t>::max());
    std::cout << event.get_msg() << std::endl;
    event.write_int8(std::numeric_limits<int8_t>::min());
    std::cout << event.get_msg() << std::endl;



    event.write_char(' ');
    std::cout << event.get_msg() << std::endl;


    event.write_int8('a');
    std::cout << event.get_msg() << std::endl;


    event.write_char(' ');
    std::cout << event.get_msg() << std::endl;


    event.write_string("1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,.");
    std::cout << event.get_msg() << std::endl;
}

int main()
{
    test_logevent();
    sol::state lua_state;
    lua_state.open_libraries();
    return 0;
}